using System;
using System.Collections;
using System.Data;
using System.Diagnostics;
using System.Text;
using PCSComMaterials.Inventory.DS;
using PCSComMaterials.Plan.DS;
using PCSComProduct.Items.DS;
using PCSComUtils.Common;
using PCSComUtils.Common.BO;
using PCSComUtils.PCSExc;
using PCSComUtils.MasterSetup.DS;

namespace PCSComMaterials.Plan.BO
{
	public class MRPRegenerationProcessBO //:  IMRPRegenerationProcessBO //
	{
		public MRPRegenerationProcessBO()
		{
			//
			// TODO: Add constructor logic here
			//
		}
		private const string REQUEST_WO_QTITY_FLD = "requestWOQtity";
		private const string REPLENISH_PO_QTITY_FLD = "ReplenishItemQtity";
		private static DataSet dstCPO;

		/// <summary>
		/// Insert a new record into database
		/// </summary>
		public void Add(object pObjectDetail)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Delete record by condition
		/// </summary>
		public void Delete(object pObjectVO)
		{
			throw new NotImplementedException();
		}
		
		/// <summary>
		/// GetCycleByMasterID
		/// </summary>
		/// <param name="pintMasterID"></param>
		/// <returns></returns>
		/// <author>Trada</author>
		/// <date>Tuesday, Feb 21 2006</date>
		//[AutoComplete(true)]
		public object GetCycleByMasterID(int pintMasterID)
		{
			MTR_MRPCycleOptionMasterDS dsMTR_MRPCycleOptionMaster = new MTR_MRPCycleOptionMasterDS();
			return dsMTR_MRPCycleOptionMaster.GetObjectVO(pintMasterID);
		}
		/// <summary>
		/// Auto Generation Process
		/// </summary>
		/// <param name="pintCCN"></param>
		/// <param name="pintMRPCycleOptionMasterID"></param>
		//[AutoComplete(true)]
		public void GenMRPPlan(int pintCCN, int pintMRPCycleOptionMasterID)
		{
			DataSet dstCalendar = (new CPODataViewerBO()).GetWorkDayCalendar();

			//Declare variables
			MTR_MRPCycleOptionDetailDS dsMRPCODetail = new MTR_MRPCycleOptionDetailDS();
			MTR_CPODS dsCPO = new MTR_CPODS();  
			ITM_ProductDS dsProduct = new ITM_ProductDS();
			MTR_MRPCycleOptionMasterDS dsCycleMaster = new MTR_MRPCycleOptionMasterDS();
			MRPRegenerationProcessDS dsMRPProcess = new MRPRegenerationProcessDS();

			//Get CycleOptionMasterVO
			MTR_MRPCycleOptionMasterVO voCOMaster = (MTR_MRPCycleOptionMasterVO) dsCycleMaster.GetObjectVO(pintMRPCycleOptionMasterID);

			if(!CheckCalendarConfig(voCOMaster))
			{
				throw new PCSBOException(ErrorCode.MESSAGE_DCP_CONFIG_CALENDAR_FROM_X_TO_Y, string.Empty, null);
			}

			//Get CycleOptionDetail
			DataSet dstCODetail = dsMRPCODetail.List(pintMRPCycleOptionMasterID);

			//Delete all Old CPO for this Cycle 
			dsCPO.Delete(pintCCN, pintMRPCycleOptionMasterID);

			//Get All MRP Non Make Item
			DataTable dtbMRPItems = dsProduct.GetMRPItems((int)PlanTypeEnum.MRP).Tables[0];

			//Declare the dataset for all information
			dstCPO = new MTR_CPODS().Search(null);
			
			DataTable dtbPONotReceipt = new DataTable();
			DataTable dtbReturnToVendor = new DataTable();
			
			if (voCOMaster.IncludedRemainPO)
			{
				DateTime dtmFromDate = voCOMaster.AsOfDate.AddDays(-voCOMaster.DaysBeforeAsOfDate);
				dtbPONotReceipt = dsMRPProcess.GetPONotReceipt(dtmFromDate, voCOMaster.AsOfDate, pintCCN);
				if (voCOMaster.IncludedReturnToVendor)
					dtbReturnToVendor = dsMRPProcess.GetReturnToVendor(dtmFromDate, voCOMaster.AsOfDate);
			}

			foreach (DataRow drowMasLoc in dstCODetail.Tables[0].Rows)
			{
				foreach (DataRow drowItem in dtbMRPItems.Rows)
				{
					MRPGenCPO(drowItem, drowMasLoc, int.Parse(drowMasLoc[MST_MasterLocationTable.MASTERLOCATIONID_FLD].ToString()),
					          voCOMaster, dstCalendar, dtbPONotReceipt, dtbReturnToVendor);
				}
			}
			if (dstCPO.Tables[0].Rows.Count <= 0)
				return;
			DataSet dstRealCPO = dstCPO.Clone();
			foreach (DataRow drowItem in dtbMRPItems.Rows)
			{
				int intPolicyDays = dsProduct.GetOrderPolicyForItem(int.Parse(drowItem[ITM_ProductTable.PRODUCTID_FLD].ToString()));
				DataRow[] drowAllItemCPO = dstCPO.Tables[0].Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowItem[ITM_ProductTable.PRODUCTID_FLD], MTR_CPOTable.DUEDATE_FLD + " ASC");
				if (drowAllItemCPO.Length > 0)
				{
					if (intPolicyDays >= 1)
					{
						int intN = 0, intResult = 0;
						DateTime dtmMaxDate = DateTime.Parse(drowAllItemCPO[drowAllItemCPO.Length-1][MTR_CPOTable.DUEDATE_FLD].ToString());
						intN = Math.DivRem(dtmMaxDate.Subtract(voCOMaster.AsOfDate).Days, intPolicyDays,out intResult);
						if (intN * intPolicyDays <  dtmMaxDate.Subtract(voCOMaster.AsOfDate).Days) intN++;
						for (int i = 0; i < intN; i++)
						{
							decimal decQuantity = 0;
							DateTime dtmDueDate = new DateTime();
							for (int j =0; j < drowAllItemCPO.Length; j++)
							{
								if (DateTime.Parse(drowAllItemCPO[j][MTR_CPOTable.DUEDATE_FLD].ToString()) >= voCOMaster.AsOfDate.AddDays(intPolicyDays*i)
									&& DateTime.Parse(drowAllItemCPO[j][MTR_CPOTable.DUEDATE_FLD].ToString()) <= voCOMaster.AsOfDate.AddDays(intPolicyDays* (i+1)))
								{
									dtmDueDate = DateTime.Parse(drowAllItemCPO[j][MTR_CPOTable.DUEDATE_FLD].ToString());                                                                                                                   
									decQuantity += decimal.Parse(drowAllItemCPO[j][MTR_CPOTable.QUANTITY_FLD].ToString());
								}
							}
							if (decQuantity > 0)
							{
								decimal decLTFixedTime = 0, decLTVari = 0, decLTDock = 0, decSafe = 0, decShip = 0, decRequis = 0;
								if (drowItem[ITM_ProductTable.LTFIXEDTIME_FLD].ToString() != string.Empty)
								{
									decLTFixedTime = decimal.Parse(drowItem[ITM_ProductTable.LTFIXEDTIME_FLD].ToString());
								}
								if (drowItem[ITM_ProductTable.LTVARIABLETIME_FLD].ToString() != string.Empty)
								{
									decLTVari = decimal.Parse(drowItem[ITM_ProductTable.LTVARIABLETIME_FLD].ToString());
								}
								if (drowItem[ITM_ProductTable.LTDOCKTOSTOCK_FLD].ToString() != string.Empty)
								{
									decLTDock = decimal.Parse(drowItem[ITM_ProductTable.LTDOCKTOSTOCK_FLD].ToString());
								}

								if (drowItem[ITM_ProductTable.LTSAFETYSTOCK_FLD].ToString() != string.Empty)
								{
									decSafe = decimal.Parse(drowItem[ITM_ProductTable.LTSAFETYSTOCK_FLD].ToString());
								}
								if (drowItem[ITM_ProductTable.LTSHIPPINGPREPARE_FLD].ToString() != string.Empty)
								{
									decShip = decimal.Parse(drowItem[ITM_ProductTable.LTSHIPPINGPREPARE_FLD].ToString());
								}
								if (drowItem[ITM_ProductTable.LTREQUISITION_FLD].ToString() != string.Empty)
								{
									decRequis = decimal.Parse(drowItem[ITM_ProductTable.LTREQUISITION_FLD].ToString());
								}
								DataRow drowNewCPO = dstRealCPO.Tables[0].NewRow();
								drowNewCPO[MTR_CPOTable.PRODUCTID_FLD] = drowItem[ITM_ProductTable.PRODUCTID_FLD];
								drowNewCPO[MTR_CPOTable.STOCKUMID_FLD] = drowItem[ITM_ProductTable.STOCKUMID_FLD];
								drowNewCPO[MTR_CPOTable.CCNID_FLD] = voCOMaster.CCNID;
								drowNewCPO[MTR_CPOTable.MASTERLOCATIONID_FLD] = drowAllItemCPO[0][MTR_CPOTable.MASTERLOCATIONID_FLD];
								drowNewCPO[MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD] = voCOMaster.MRPCycleOptionMasterID;
								drowNewCPO[MTR_CPOTable.DUEDATE_FLD] = dtmDueDate;
								drowNewCPO[MTR_CPOTable.STARTDATE_FLD] = //new UtilsBO().ConvertWorkingDay(dtmDueDate, Math.Abs(decLTFixedTime/(60*60*24) + decQuantity*decLTVari/(60*60*24) + decLTDock/(60*60*24) + decSafe/(60*60*24) +      decShip/(60*60*24) + decRequis/(60*60*24)), ScheduleMethodEnum.Backward);
									GetNearestWorkingDay(dtmDueDate, Math.Abs(decLTFixedTime/(60*60*24) + decQuantity*decLTVari/(60*60*24) + decLTDock/(60*60*24) + decSafe/(60*60*24) +      decShip/(60*60*24) + decRequis/(60*60*24)),dstCalendar);
								drowNewCPO[MTR_CPOTable.QUANTITY_FLD] = decQuantity;
								drowNewCPO[MTR_CPOTable.ISMPS_FLD] = false;
								dstRealCPO.Tables[0].Rows.Add(drowNewCPO);
							}
						}
					}
					else
					{
						foreach (DataRow drowCPO in drowAllItemCPO)
						{
							drowCPO[MTR_CPOTable.ISMPS_FLD] = false;
							dstRealCPO.Tables[0].ImportRow(drowCPO);
						}
					}
				}
			}
			//Update dataset
			dsCPO.UpdateDataSet(dstRealCPO);

			//Update RegenDate
			if (dstRealCPO.Tables[0].Rows.Count > 0)
				dsCycleMaster.UpdateGenDate(pintMRPCycleOptionMasterID);
		}


		/// <summary>
		/// 
		/// </summary>
		/// <param name="pdtAsOfDate"></param>
		/// <param name="pintThroughHorizon"></param>
		/// <returns></returns>
		//[AutoComplete(true)]
		private DateTime GetLimitPlaningCycle(DateTime pdtAsOfDate ,int pintThroughHorizon)
		{
			try
			{
				DateTime dtReturn = pdtAsOfDate.AddDays(pintThroughHorizon);
				dtReturn = new DateTime(dtReturn.Year, dtReturn.Month, dtReturn.Day, 23, 59, 59);
				return dtReturn;
			}
			catch (PCSDBException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				throw new Exception(ex.Message, ex);
			}
		}


		/// <summary>
		/// Get the object information by ID of VO class
		/// </summary>
		public object GetObjectVO(int pintID, string VOclass)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// MRP Generation CPO
		/// </summary>
		/// <param name="pdrowItem"></param>
		/// <param name="pintMasLocID"></param>
		/// <param name="pvoCycleMaster"></param>
		//[AutoComplete(true)]
		public void MRPGenCPO(DataRow pdrowItem, DataRow pdrowCODetail, int pintMasLocID, MTR_MRPCycleOptionMasterVO pvoCycleMaster,DataSet pdstCalendar,
			DataTable pdtbPONotReceipt, DataTable pdtbReturnToVendor)
		{
			try
			{
				int intProductID = int.Parse(pdrowItem[ITM_ProductTable.PRODUCTID_FLD].ToString().Trim());
				DateTime dtDueDate  = GetLimitPlaningCycle(pvoCycleMaster.AsOfDate, pvoCycleMaster.PlanHorizon);
                 

				MRPRegenerationProcessDS dsMRPRegen = new MRPRegenerationProcessDS();
				IV_MasLocCacheDS dsMasLoc = new IV_MasLocCacheDS();
				
				//Get All Request Items
				//Step 1 : Get for MPSItems
				//Step 2 : Get for MRPItems
				decimal decAvailable = 0;
				if (pdrowCODetail[MTR_MRPCycleOptionDetailTable.ONHAND_FLD].ToString() == true.ToString())
					decAvailable = dsMasLoc.GetAvailableQuantity(pvoCycleMaster.CCNID,  pintMasLocID, intProductID);
				if (decAvailable == decimal.MinusOne) decAvailable = 0;
				
				#region 29-06-2006 dungla: recalculate begin onhand quantity based on cycle option
				
				decimal decPONotReceipt = 0, decReturnToVendor = 0;
				if (pvoCycleMaster.IncludedRemainPO)
				{
					string strFilter = "MasterLocationID = '" + pintMasLocID + "' AND ProductID = '" + intProductID + "'";
					try
					{
						decPONotReceipt = Convert.ToDecimal(pdtbPONotReceipt.Compute("SUM(Quantity)", strFilter));
					}
					catch{}
					if (pvoCycleMaster.IncludedReturnToVendor)
					{
						try
						{
							decReturnToVendor = Convert.ToDecimal(pdtbReturnToVendor.Compute("SUM(Quantity)", strFilter));
						}
						catch{}
					}
				}
				
				// Begin OH = OH(AsofDate) + Sum(PO.Delivery - POReceipt) - Sum(ReturnToVendor)
				decAvailable = decAvailable + decPONotReceipt - decReturnToVendor;
				
				#endregion
				
				decimal decRequest = 0, decReplenish = 0;
				DataTable dtbItemsReplenish = new DataTable();
				DataTable dtbAllRequest = new DataTable();
				dtbAllRequest.Columns.Add(MTR_CPOTable.DUEDATE_FLD, typeof(DateTime));
				dtbAllRequest.Columns.Add(REQUEST_WO_QTITY_FLD, typeof(decimal));

				//Step 1 : Get all request from CollectMPSItems for item in CollectMRPItems
				DataTable dtbMPSDetail = new MTR_MPSCycleOptionDetailDS().List(pvoCycleMaster.MPSCycleOptionMasterID).Tables[0];
				if (dtbMPSDetail.Select(MTR_MPSCycleOptionDetailTable.MASTERLOCATIONID_FLD + " = " + pintMasLocID).Length != 0)
				{
					DataTable dtbTempCPOItems = dsMRPRegen.getAllCPOForItem(intProductID, dtDueDate, pvoCycleMaster.AsOfDate, pintMasLocID, pvoCycleMaster.MPSCycleOptionMasterID);
					ImportRows(dtbAllRequest, dtbTempCPOItems, 1);
				}

				DataTable dtbTempWOItems = new DataTable();
				if (pdrowCODetail[MTR_MRPCycleOptionDetailTable.DEMANDWO_FLD].ToString() == true.ToString())
					dtbTempWOItems= dsMRPRegen.getAllReleaseWOForItem(intProductID, dtDueDate, pvoCycleMaster.AsOfDate, pintMasLocID);
				ImportRows(dtbAllRequest, dtbTempWOItems, 1);
				//Step 2 : Get all request for Items

				DataTable dtbTempSOItems = new DataTable(); 
				if (pdrowCODetail[MTR_MRPCycleOptionDetailTable.SALEORDER_FLD].ToString() == true.ToString())
					dtbTempSOItems = dsMRPRegen.getAllReleaseSOForItem(intProductID, dtDueDate, pvoCycleMaster.AsOfDate, pintMasLocID);
 

				//Get All Replenish Items
				dtbItemsReplenish = new DataTable(); 
				const string Has_Used = "HasUsed";
				if (pdrowCODetail[MTR_MRPCycleOptionDetailTable.PURCHASEORDER_FLD].ToString() == true.ToString())
					dtbItemsReplenish =      dsMRPRegen.getAllReleasePOForItem(intProductID, dtDueDate, pvoCycleMaster.AsOfDate,  pintMasLocID);
					dtbItemsReplenish.Columns.Add(Has_Used);
				ImportRows(dtbAllRequest, dtbTempSOItems, 0);
				dtbAllRequest = SortTable(dtbAllRequest, MTR_CPOTable.DUEDATE_FLD);
				//Get all request item from CPO, WO, SO
				int intStep = 0;
				DateTime dtmDueDate = new DateTime();
				for (int i =0 + intStep; i < dtbAllRequest.Rows.Count; i++)
				{
					decRequest = (decimal) dtbAllRequest.Rows[i][REQUEST_WO_QTITY_FLD];
					dtmDueDate = (DateTime) dtbAllRequest.Rows[i][MTR_CPOTable.DUEDATE_FLD];
					for (int j = i+1; j < dtbAllRequest.Rows.Count; j++)
					{
						if (dtbAllRequest.Rows[i][MTR_CPOTable.DUEDATE_FLD] == dtbAllRequest.Rows[j][MTR_CPOTable.DUEDATE_FLD])
						{
							decRequest += (decimal) dtbAllRequest.Rows[j][REQUEST_WO_QTITY_FLD];
						}
						else
						{
							intStep = j+1;
							break;
						}
					}
					foreach (DataRow drowItem in dtbItemsReplenish.Rows)
					{
						if ((DateTime)drowItem[PO_DeliveryScheduleTable.SCHEDULEDATE_FLD] <= (DateTime)dtbAllRequest.Rows[i][MTR_CPOTable.DUEDATE_FLD]
							&& drowItem[Has_Used].ToString() == string.Empty)
						{
							decReplenish += (decimal) drowItem[REPLENISH_PO_QTITY_FLD]; 
							drowItem[Has_Used] = 1;
						}
					}

					decimal decRemain = decAvailable - decRequest;
					decimal decReal;
					if (decRemain >= 0)
					{
						decAvailable = decRemain;
					}
					if (decRemain < 0)
					{
						decRemain = decRemain + decReplenish;
						if (decRemain >= 0)
						{
							decReplenish = decRemain;	
						}
					}
					if (decRemain < 0)
					{
						decReplenish = 0;
						decRemain = -decRemain;
						decReal = decRemain;
						DataRow drowCPO = dstCPO.Tables[0].NewRow();
						drowCPO[MTR_CPOTable.PRODUCTID_FLD] = intProductID;
						drowCPO[MTR_CPOTable.STOCKUMID_FLD] = int.Parse(pdrowItem[ITM_ProductTable.STOCKUMID_FLD].ToString());
						drowCPO[MTR_CPOTable.DUEDATE_FLD] = dtmDueDate;
						drowCPO[MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD] = pvoCycleMaster.MRPCycleOptionMasterID;
						drowCPO[MTR_CPOTable.MASTERLOCATIONID_FLD] = pintMasLocID;
						drowCPO[MTR_CPOTable.CCNID_FLD] = pvoCycleMaster.CCNID;
						if (pdrowItem[ITM_ProductTable.SCRAPPERCENT_FLD].ToString() != string.Empty)
						{
							decRemain = decRemain * 100 / (100 - decimal.Parse(pdrowItem[ITM_ProductTable.SCRAPPERCENT_FLD].ToString()));     
						}
						if (i == 0 && pdrowItem[ITM_ProductTable.SAFETYSTOCK_FLD].ToString() != string.Empty)
						{
							decRemain += decimal.Parse(pdrowItem[ITM_ProductTable.SAFETYSTOCK_FLD].ToString());
							decReal += decimal.Parse(pdrowItem[ITM_ProductTable.SAFETYSTOCK_FLD].ToString());
						}
						if ( pdrowItem[ITM_ProductTable.LOTSIZE_FLD].ToString() != string.Empty
							&& int.Parse(pdrowItem[ITM_ProductTable.LOTSIZE_FLD].ToString()) > 0)

						{
							decRemain = Math.Max(decRemain, decimal.Parse(pdrowItem[ITM_ProductTable.LOTSIZE_FLD].ToString()));
							if (decRemain <= int.Parse(pdrowItem[ITM_ProductTable.LOTSIZE_FLD].ToString()))
							{
								decRemain = int.Parse(pdrowItem[ITM_ProductTable.LOTSIZE_FLD].ToString());	
							}
							else
							{
								decimal intMulti = decimal.Floor(decRemain/int.Parse(pdrowItem[ITM_ProductTable.LOTSIZE_FLD].ToString()));
								if (intMulti* int.Parse(pdrowItem[ITM_ProductTable.LOTSIZE_FLD].ToString()) < decRemain)
								{
									decRemain = (intMulti+1)* int.Parse(pdrowItem[ITM_ProductTable.LOTSIZE_FLD].ToString());
								}
							}
						}
						if (pdrowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString().Trim() != string.Empty && decRemain < decimal.Parse(pdrowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString()))
						{
							decRemain = decimal.Parse(pdrowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString());
						}
						if (pdrowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString().Trim() != string.Empty && pdrowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString() != string.Empty && decimal.Parse(pdrowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString()) != 0 

							&& (decRemain - decimal.Parse(pdrowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString().Trim())) % Convert.ToInt32(Math.Round(decimal.Parse(pdrowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString())) ) != 0)
						{
							decRemain = Convert.ToDecimal(double.Parse(pdrowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString().Trim()) 
								+ Math.Ceiling(Convert.ToDouble(decRemain - decimal.Parse(pdrowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString().Trim()))/double.Parse(pdrowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString())) * double.Parse(pdrowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString()));
						}
						drowCPO[MTR_CPOTable.QUANTITY_FLD] = decRemain;
						decimal decLTFixedTime = 0, decLTVari = 0, decLTDock = 0, decSafe = 0, decShip = 0, decRequis = 0;
						if (pdrowItem[ITM_ProductTable.LTFIXEDTIME_FLD].ToString() != string.Empty)
						{
							decLTFixedTime = decimal.Parse(pdrowItem[ITM_ProductTable.LTFIXEDTIME_FLD].ToString());
						}
						if (pdrowItem[ITM_ProductTable.LTVARIABLETIME_FLD].ToString() != string.Empty)
						{
							decLTVari = decimal.Parse(pdrowItem[ITM_ProductTable.LTVARIABLETIME_FLD].ToString());
						}

						if (pdrowItem[ITM_ProductTable.LTDOCKTOSTOCK_FLD].ToString() != string.Empty)
						{
							decLTDock = decimal.Parse(pdrowItem[ITM_ProductTable.LTDOCKTOSTOCK_FLD].ToString());
						}
						if (pdrowItem[ITM_ProductTable.LTSAFETYSTOCK_FLD].ToString() != string.Empty)
						{
							decSafe = decimal.Parse(pdrowItem[ITM_ProductTable.LTSAFETYSTOCK_FLD].ToString());
						}

						if (pdrowItem[ITM_ProductTable.LTSHIPPINGPREPARE_FLD].ToString() != string.Empty)
						{
							decShip = decimal.Parse(pdrowItem[ITM_ProductTable.LTSHIPPINGPREPARE_FLD].ToString());
						}
						if (pdrowItem[ITM_ProductTable.LTREQUISITION_FLD].ToString() != string.Empty)
						{
							decRequis = decimal.Parse(pdrowItem[ITM_ProductTable.LTREQUISITION_FLD].ToString());
						}
						drowCPO[MTR_CPOTable.STARTDATE_FLD] = //boUtils.ConvertWorkingDay((DateTime)drowCPO[MTR_CPOTable.DUEDATE_FLD], Math.Abs(decLTFixedTime/(60*60*24) + decRemain*decLTVari/(60*60*24) + decLTDock/(60*60*24) + decSafe/(60*60*24) +    decShip/(60*60*24) + decRequis/(60*60*24)), ScheduleMethodEnum.Backward);
							GetNearestWorkingDay((DateTime)drowCPO[MTR_CPOTable.DUEDATE_FLD], Math.Abs(decLTFixedTime/(60*60*24) + decRemain*decLTVari/(60*60*24) + decLTDock/(60*60*24) + decSafe/(60*60*24) +    decShip/(60*60*24) + decRequis/(60*60*24)), pdstCalendar);
 
						dstCPO.Tables[0].Rows.Add(drowCPO);
						if (pdrowItem[ITM_ProductTable.SCRAPPERCENT_FLD].ToString() != string.Empty)
						{
							decAvailable = decRemain*(100-decimal.Parse(pdrowItem[ITM_ProductTable.SCRAPPERCENT_FLD].ToString()))/100 - decReal;
						}
						else
						{
							decAvailable = decRemain - decReal;
						}
					}
				}
			}
			catch (PCSDBException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				throw new Exception(ex.Message, ex);
			}
		}


		/// <summary>
		/// MRP Generation CPO
		/// </summary>
		/// <param name="pintMasLocID"></param>
		/// <param name="pvoCycleMaster"></param>
		//[AutoComplete(true)]
		public DataTable MRPGenCPOOffLine(DataTable pdtbWorkingDays, DataTable pdtbHolidays, DataTable pdtbItems, DataRow pdrowCODetail, int pintMasLocID, MTR_MRPCycleOptionMasterVO pvoCycleMaster,
			DataTable pdtbPONotReceipt, DataTable pdtbPOReceipt, DataTable pdtbReturnToVendor, DateTime dtmServerDate)
		{
			const string HASUSED_FLD = "HasUsed";

			MRPRegenerationProcessDS dsMRPRegen = new MRPRegenerationProcessDS();
			IV_MasLocCacheDS dsMasLocCache = new IV_MasLocCacheDS();
			IV_BalanceBinDS dsBalanceBin = new IV_BalanceBinDS();
			DateTime dtDueDate  = GetLimitPlaningCycle(pvoCycleMaster.AsOfDate, pvoCycleMaster.PlanHorizon);
			StringBuilder strSQLItems = BuildSQLIN(pdtbItems);
			DataTable dtbAvailable = new DataTable();
			DateTime dtmBeginMonth = new DateTime(dtmServerDate.Year, dtmServerDate.Month, 1);

			#region begin for niguri

			DataTable dtbBeginForNIGURI = dsMasLocCache.GetBeginQuantityOfNiguri(pvoCycleMaster.AsOfDate);
			
			#endregion

			//Get All Request Items
			//Step 1 : Get for MPSItems
			//Step 2 : Get for MRPItems
			if (pdrowCODetail[MTR_MRPCycleOptionDetailTable.ONHAND_FLD].ToString() == true.ToString())
				dtbAvailable = dsBalanceBin.GetAvailableQuantityForPlan(dtmBeginMonth);
				
			DataTable dtbItemsReplenish = new DataTable();
			DataTable dtbAllRequest = new DataTable();
			dtbAllRequest.Columns.Add(MTR_CPOTable.DUEDATE_FLD, typeof(DateTime));
			dtbAllRequest.Columns.Add(ITM_ProductTable.PRODUCTID_FLD);
			dtbAllRequest.Columns.Add(REQUEST_WO_QTITY_FLD, typeof(decimal));

			//Get remain quantity from now to AsOfDate
			DataTable dtbAllRequestPrevious = dtbAllRequest.Copy();
			DataTable dtbItemsReplenishPrevious = dsMRPRegen.getAllReleasePOForItems(strSQLItems, dtmBeginMonth, pvoCycleMaster.AsOfDate,  pintMasLocID);
			ImportAllRows(dtbAllRequestPrevious, dsMRPRegen.getAllReleaseSOForItems(strSQLItems, dtmBeginMonth, pvoCycleMaster.AsOfDate, pintMasLocID), 0);
			// change request: use unrelease work order
			ImportAllRows(dtbAllRequestPrevious, dsMRPRegen.getAllUnReleaseWOForItems(strSQLItems, dtmBeginMonth, pvoCycleMaster.AsOfDate, pintMasLocID), 0);
				
			DataTable dtbTempWOItems = new DataTable();
			if (pdrowCODetail[MTR_MRPCycleOptionDetailTable.DEMANDWO_FLD].ToString() == true.ToString())
			{
				dtbTempWOItems= dsMRPRegen.getAllUnReleaseWOForItems(strSQLItems, pvoCycleMaster.AsOfDate, dtDueDate, pintMasLocID);
				ImportAllRows(dtbAllRequest, dtbTempWOItems, 1);
			}

			//Step 2 : Get all request for Items
			DataTable dtbTempSOItems = new DataTable(); 
			if (pdrowCODetail[MTR_MRPCycleOptionDetailTable.SALEORDER_FLD].ToString() == true.ToString())
			{
				dtbTempSOItems = dsMRPRegen.getAllReleaseSOForItemsInCycle(strSQLItems, pvoCycleMaster.AsOfDate, dtDueDate, pintMasLocID);
				ImportAllRows(dtbAllRequest, dtbTempSOItems, 0);
			}

			//Get All Replenish Items
			dtbItemsReplenish = new DataTable(); 
			if (pdrowCODetail[MTR_MRPCycleOptionDetailTable.PURCHASEORDER_FLD].ToString() == true.ToString())
				dtbItemsReplenish =   dsMRPRegen.getAllReleasePOForItems(strSQLItems, pvoCycleMaster.AsOfDate, dtDueDate, pintMasLocID, pvoCycleMaster.CCNID);
			dtbItemsReplenish.Columns.Add(HASUSED_FLD);

			foreach (DataRow drowData in pdtbItems.Rows)
			{
				int intStep = 0;
				DateTime dtmDueDate = new DateTime();

				DataRow[] drowAllItemsRequest = dtbAllRequest.Select(ITM_ProductTable.PRODUCTID_FLD + "='" + drowData[ITM_ProductTable.PRODUCTID_FLD].ToString() + "'");
				drowAllItemsRequest = SortListItems(drowAllItemsRequest, MTR_CPOTable.DUEDATE_FLD);
				DataRow[] drowAllItemsReplenish;
				if (dtbItemsReplenish.Rows.Count > 0)
				{
					drowAllItemsReplenish = dtbItemsReplenish.Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowData[ITM_ProductTable.PRODUCTID_FLD].ToString());
				}
				else
					drowAllItemsReplenish = new DataRow[0];

				int nProductID = 0, nLocationID = 0;
				try
				{
					nProductID = (int)drowData[ITM_ProductTable.PRODUCTID_FLD];
				}
				catch{}
				try
				{
					nLocationID = (int)drowData[ITM_ProductTable.LOCATIONID_FLD];
				}
				catch{}
				string strFilterByLocation = ITM_ProductTable.PRODUCTID_FLD + "=" + nProductID
						+ " AND " + ITM_ProductTable.LOCATIONID_FLD + "=" + nLocationID;

				#region 09-10-2006 dungla: calculate stock at as of date for NIGURI REPORT

				decimal decLocationQuantity = 0;
				try
				{
					decLocationQuantity += Convert.ToDecimal(dtbAvailable.Compute("SUM(" + Constants.SUPPLY_QUANTITY_FLD + ")", strFilterByLocation));
				}
				catch{}

				#endregion

				decimal decAvailable = 0, decAvailableNIGURY = 0;
				if (pdrowCODetail[MTR_MRPCycleOptionDetailTable.ONHAND_FLD].ToString() == true.ToString())
				{
					decAvailable = GetAllRemainBeforeRun((int) drowData[ITM_ProductTable.PRODUCTID_FLD], dtbAllRequestPrevious, dtbItemsReplenishPrevious);
					decAvailableNIGURY = decAvailable;

					#region thuytpt request: move demand from safety stock to end of cycle

					if (drowData[ITM_ProductTable.SAFETYSTOCK_FLD].ToString() != string.Empty)
					{
						decAvailable -= (decimal)drowData[ITM_ProductTable.SAFETYSTOCK_FLD];
					}

					#endregion

					decLocationQuantity += decAvailableNIGURY;
					DataRow[] drowAvaiItems;
					if (dtbAvailable.Rows.Count > 0)
					{
						drowAvaiItems = dtbAvailable.Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowData[ITM_ProductTable.PRODUCTID_FLD].ToString());
					}
					else
						drowAvaiItems = new DataRow[0];
					if (drowAvaiItems.Length > 0)
					{
						try
						{
							decAvailable += Convert.ToDecimal(dtbAvailable.Compute("SUM(" + Constants.SUPPLY_QUANTITY_FLD + ")",
								ITM_ProductTable.PRODUCTID_FLD + "=" + drowData[ITM_ProductTable.PRODUCTID_FLD].ToString()));
							decAvailableNIGURY += Convert.ToDecimal(dtbAvailable.Compute("SUM(" + Constants.SUPPLY_QUANTITY_FLD + ")",
								ITM_ProductTable.PRODUCTID_FLD + "=" + drowData[ITM_ProductTable.PRODUCTID_FLD].ToString()));
						}
						catch{}
					}
				}

				#region 29-06-2006 dungla: recalculate begin onhand quantity based on cycle option
				
				decimal decPONotReceipt = 0, decReturnToVendor = 0;
				if (pvoCycleMaster.IncludedRemainPO)
				{
					string strFilter = "MasterLocationID = '" + pintMasLocID + "' AND ProductID = '" + drowData[ITM_ProductTable.PRODUCTID_FLD] + "'";
					try
					{
						decPONotReceipt = Convert.ToDecimal(pdtbPOReceipt.Compute("SUM(Quantity)", strFilter));
					}
					catch{}
					try
					{
						decPONotReceipt -= Convert.ToDecimal(pdtbPONotReceipt.Compute("SUM(Quantity)", strFilter));
					}
					catch{}
					if (pvoCycleMaster.IncludedReturnToVendor)
					{
						try
						{
							decReturnToVendor = Convert.ToDecimal(pdtbReturnToVendor.Compute("SUM(Quantity)", strFilter));
						}
						catch{}
					}
				}
				// Begin OH = OH(AsofDate) + Sum(PO.Delivery - POReceipt) - Sum(ReturnToVendor)
				decAvailable = decAvailable - decPONotReceipt - decReturnToVendor;
				decAvailableNIGURY = decAvailableNIGURY - decPONotReceipt - decReturnToVendor;
				decLocationQuantity = decLocationQuantity - decPONotReceipt - decReturnToVendor;
				DataRow[] drowsBegin = dtbBeginForNIGURI.Select(ITM_ProductTable.PRODUCTID_FLD + "=" + nProductID
					+ " AND " + ITM_ProductTable.LOCATIONID_FLD + "=" + nLocationID
					+ " AND " + IV_BeginMRPTable.ASOFTDATE_FLD + "='" + pvoCycleMaster.AsOfDate.ToString("G") + "'");
				if (drowsBegin.Length > 0) // already exits, need to update new quantity
				{
					drowsBegin[0][IV_BeginMRPTable.QUANTITY_FLD] = decLocationQuantity;
					drowsBegin[0][IV_BeginMRPTable.QUANTITYMAP_FLD] = decAvailableNIGURY;
				}
				else // make a new record
				{
					DataRow drowBegin = dtbBeginForNIGURI.NewRow();
					drowBegin[IV_BeginMRPTable.ASOFTDATE_FLD] = pvoCycleMaster.AsOfDate;
					if (nLocationID == 0)
						drowBegin[IV_BeginMRPTable.LOCATIONID_FLD] = DBNull.Value;
					else
						drowBegin[IV_BeginMRPTable.LOCATIONID_FLD] = nLocationID;
					drowBegin[IV_BeginMRPTable.PRODUCTID_FLD] = drowData[ITM_ProductTable.PRODUCTID_FLD];
					drowBegin[IV_BeginMRPTable.QUANTITY_FLD] = decLocationQuantity;
					drowBegin[IV_BeginMRPTable.QUANTITYMAP_FLD] = decAvailableNIGURY;
					dtbBeginForNIGURI.Rows.Add(drowBegin); 
				}
				
				#endregion
					
				decimal decRequest = 0, decReplenish = 0;
				for (int i =0 + intStep; i < drowAllItemsRequest.Length; i++)
				{
					try
					{
						decRequest = (decimal) drowAllItemsRequest[i][REQUEST_WO_QTITY_FLD];
					}
					catch (Exception ex)
					{
						Debug.WriteLine(ex.Message);
					}
					dtmDueDate = (DateTime) drowAllItemsRequest[i][MTR_CPOTable.DUEDATE_FLD];
					for (int j = i+1; j < drowAllItemsRequest.Length; j++)
					{
						if (drowAllItemsRequest[i][MTR_CPOTable.DUEDATE_FLD] == drowAllItemsRequest[j][MTR_CPOTable.DUEDATE_FLD])
						{
							decRequest += decimal.Parse(drowAllItemsRequest[j][REQUEST_WO_QTITY_FLD].ToString());
						}
						else
						{
							intStep = j+1;
							break;
						}
					}
					foreach (DataRow drowItem in drowAllItemsReplenish)
					{
						if ((DateTime) drowItem[PO_DeliveryScheduleTable.SCHEDULEDATE_FLD] <= (DateTime) drowAllItemsRequest[i][MTR_CPOTable.DUEDATE_FLD]
							&& drowItem[HASUSED_FLD].ToString() == string.Empty)
						{
							decReplenish += decimal.Parse(drowItem[REPLENISH_PO_QTITY_FLD].ToString()); 
							drowItem[HASUSED_FLD] = 1;
						}
					}
					decimal decRemain = decAvailable - decRequest;
					decimal decReal;
					if (decRemain >= 0)
						decAvailable = decRemain;
					else
						decAvailable = 0;
					if (decRemain < 0)
					{
						decRemain = decRemain + decReplenish;
						if (decRemain >= 0)
							decReplenish = decRemain;
						else
							decReplenish = 0;
					}
					if (decRemain < 0)
					{
						decReplenish = 0;
						decRemain = -decRemain;
						decReal = decRemain;
						DataRow drowCPO = dstCPO.Tables[0].NewRow();
						drowCPO[MTR_CPOTable.PRODUCTID_FLD] = drowData[ITM_ProductTable.PRODUCTID_FLD];
						drowCPO[MTR_CPOTable.STOCKUMID_FLD] = drowData[ITM_ProductTable.STOCKUMID_FLD];

						#region 12-08-2006 dungla edit for thuypt request: due date must substract sale atp

						double dblSaleATP = 0;
						try
						{
							dblSaleATP = Convert.ToDouble(drowData[ITM_ProductTable.LTSALESATP_FLD]);
						}
						catch{}
						drowCPO[MTR_CPOTable.DUEDATE_FLD] = dtmDueDate.AddDays( - dblSaleATP);

						#endregion

						drowCPO[MTR_CPOTable.MASTERLOCATIONID_FLD] = pintMasLocID;
						drowCPO[MTR_CPOTable.CCNID_FLD] = pvoCycleMaster.CCNID;
						if (drowData[ITM_ProductTable.SCRAPPERCENT_FLD].ToString() != string.Empty)
						{
							decRemain = decRemain * 100 / (100 - decimal.Parse(drowData[ITM_ProductTable.SCRAPPERCENT_FLD].ToString()));     
						}
						if ( drowData[ITM_ProductTable.LOTSIZE_FLD].ToString() != string.Empty
							&& int.Parse(drowData[ITM_ProductTable.LOTSIZE_FLD].ToString()) > 0)
						{
							decRemain = Math.Max(decRemain, decimal.Parse(drowData[ITM_ProductTable.LOTSIZE_FLD].ToString()));
							if (decRemain <= int.Parse(drowData[ITM_ProductTable.LOTSIZE_FLD].ToString()))
							{
								decRemain = int.Parse(drowData[ITM_ProductTable.LOTSIZE_FLD].ToString());	
							}
							else
							{
								decimal intMulti = decimal.Floor(decRemain/int.Parse(drowData[ITM_ProductTable.LOTSIZE_FLD].ToString()));
								if (intMulti* int.Parse(drowData[ITM_ProductTable.LOTSIZE_FLD].ToString()) < decRemain)
								{
									decRemain = (intMulti+1)* int.Parse(drowData[ITM_ProductTable.LOTSIZE_FLD].ToString());
								}
							}
						}
						if (decRemain != decimal.Truncate(decRemain))
							decRemain = decimal.Truncate(decRemain) + 1;

						drowCPO[MTR_CPOTable.QUANTITY_FLD] = decRemain;
						dstCPO.Tables[0].Rows.Add(drowCPO);
						if (drowData[ITM_ProductTable.SCRAPPERCENT_FLD].ToString() != string.Empty)
						{
							decAvailable = decRemain*(100-decimal.Parse(drowData[ITM_ProductTable.SCRAPPERCENT_FLD].ToString()))/100 - decReal;
						}
						else
						{
							decAvailable = decRemain - decReal;
						}
					}
				}
			}
			return dtbBeginForNIGURI;
		}
		
		//[AutoComplete(true)]
		public void GetAllCommonDataBeforeCalcule(int pintCCN, int pintMRPCycleOptionMasterID, MTR_MRPCycleOptionMasterVO poutvoMRPCycle,
			out DataTable poutdtbWorkingDays,
			out DataTable poutdtbHolidays)
		{
			MTR_MRPCycleOptionMasterDS dsCycleMaster = new MTR_MRPCycleOptionMasterDS();
			poutvoMRPCycle = (MTR_MRPCycleOptionMasterVO) dsCycleMaster.GetObjectVO(pintMRPCycleOptionMasterID);

			MRPRegenerationProcessDS dsMRP = new MRPRegenerationProcessDS();
			poutdtbWorkingDays = dsMRP.GetAllWorkingDays();

			poutdtbHolidays = dsMRP.GetAllHolidays(ScheduleMethodEnum.Backward);
		}

		/// <summary>
		/// Auto Generation Process
		/// </summary>
		/// <param name="pintCCN"></param>
		/// <param name="pintMRPCycleOptionMasterID"></param>
		//[AutoComplete(true)]
		public void GenMRPPlanOffLine(int pintCCN, int pintMRPCycleOptionMasterID, string pstrVendorID,
			string pstrCategoryID, string pstrModel, string pstrProductID)
		{
			//Declare variables
			MTR_MRPCycleOptionDetailDS dsMRPCODetail = new MTR_MRPCycleOptionDetailDS();
			MTR_CPODS dsCPO = new MTR_CPODS();  
			ITM_ProductDS dsProduct = new ITM_ProductDS();
			MTR_MRPCycleOptionMasterDS dsCycleMaster = new MTR_MRPCycleOptionMasterDS();

			//Get CycleOptionMasterVO
			MTR_MRPCycleOptionMasterVO voCOMaster = (MTR_MRPCycleOptionMasterVO) dsCycleMaster.GetObjectVO(pintMRPCycleOptionMasterID);

			MRPRegenerationProcessDS dsMRP = new MRPRegenerationProcessDS();
			DataTable dtbWorkingDays = dsMRP.GetAllWorkingDays();
			DataTable dtbHolidays = dsMRP.GetAllHolidays(ScheduleMethodEnum.Backward);
				
			if(!CheckCalendarConfig(voCOMaster))
				throw new PCSBOException(ErrorCode.MESSAGE_DCP_CONFIG_CALENDAR_FROM_X_TO_Y, string.Empty, null);

			//Get CycleOptionDetail
			DataSet dstCODetail = dsMRPCODetail.List(pintMRPCycleOptionMasterID);

			//Delete all Old CPO for this Cycle 
			dsCPO.Delete(pintCCN, pintMRPCycleOptionMasterID, pstrVendorID, pstrCategoryID, pstrModel, pstrProductID);

			//Get All MRP Non Make Item
			DataTable dtbMRPItems = dsProduct.GetMRPItems(pstrVendorID, pstrCategoryID, pstrModel, pstrProductID).Tables[0];

			//Get All Order Policies for all Items
			DataTable dtbOrderPolicy = dsProduct.GetOrderPolicyByProducts(BuildSQLIN(dtbMRPItems));

			MRPRegenerationProcessDS dsMRPProcess = new MRPRegenerationProcessDS();

			DataTable dtbPONotReceipt = new DataTable();
			DataTable dtbPOReceipt = new DataTable();
			DataTable dtbReturnToVendor = new DataTable();
			DateTime dtmServerDate = new UtilsBO().GetDBDate();
			
			if (voCOMaster.IncludedRemainPO)
			{
				// change request: begin of current month minus day before
				DateTime dtmBeginMonth = new DateTime(dtmServerDate.Year, dtmServerDate.Month, 1);
				DateTime dtmFromDate = dtmBeginMonth.AddDays(-voCOMaster.DaysBeforeAsOfDate);
				dtbPONotReceipt = dsMRPProcess.GetPONotReceipt(dtmFromDate, dtmBeginMonth, pintCCN);
				dtbPOReceipt = dsMRPProcess.GetPOReceipt(dtmFromDate, dtmBeginMonth, pintCCN);
				if (voCOMaster.IncludedReturnToVendor)
					dtbReturnToVendor = dsMRPProcess.GetReturnToVendor(dtmFromDate, dtmBeginMonth);
			}
			
			//Declare the dataset for all information (Scan all MasLoc)
			foreach (DataRow drowMasLoc in dstCODetail.Tables[0].Rows)
			{
				dstCPO = new MTR_CPODS().Search(null);
				DataTable dtbBeginNIGURI = MRPGenCPOOffLine(dtbWorkingDays, dtbHolidays, dtbMRPItems, drowMasLoc, int.Parse(drowMasLoc[MST_MasterLocationTable.MASTERLOCATIONID_FLD].ToString()), voCOMaster, 
					dtbPONotReceipt, dtbPOReceipt, dtbReturnToVendor, dtmServerDate);
				

				DateTime dtmToDate = GetLimitPlaningCycle(voCOMaster.AsOfDate, voCOMaster.PlanHorizon);
				if (dstCPO.Tables[0].Rows.Count <= 0)
				{
					UpdateBegin(pintMRPCycleOptionMasterID, dtbBeginNIGURI, voCOMaster.AsOfDate, dtmToDate,
						pintCCN, pstrVendorID, pstrCategoryID, pstrModel, pstrProductID);
					return;
				}
				dstCPO.Tables[0].Rows[0][MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD] = pintMRPCycleOptionMasterID;
				DataSet dstRealCPO = dstCPO.Clone();
				foreach (DataRow drowItem in dtbMRPItems.Rows)
				{
					DataRow[] drowPolicyItems = dtbOrderPolicy.Select(ITM_ProductTable.PRODUCTID_FLD + "='" + drowItem[ITM_ProductTable.PRODUCTID_FLD].ToString() + "'");
					if (drowPolicyItems.Length > 0)
					{
						DataRow drowPolicys = drowPolicyItems[0];
						if (drowPolicys[ITM_OrderPolicyTable.CODE_FLD].ToString() == OrderPolicyEnum.Daily.ToString().ToUpper())
						{
							dstRealCPO = GroupByOrderPolicys(drowItem, dstRealCPO, dstCPO, OrderPolicyEnum.Daily, dtbWorkingDays, dtbHolidays);
						}
						else if (drowPolicys[ITM_OrderPolicyTable.CODE_FLD].ToString() == OrderPolicyEnum.Weekly.ToString().ToUpper())
						{
							dstRealCPO = GroupByOrderPolicys(drowItem, dstRealCPO, dstCPO, OrderPolicyEnum.Weekly, dtbWorkingDays, dtbHolidays);
						}
						else if (drowPolicys[ITM_OrderPolicyTable.CODE_FLD].ToString() == OrderPolicyEnum.Monthly.ToString().ToUpper())
						{
							dstRealCPO = GroupByOrderPolicys(drowItem, dstRealCPO, dstCPO, OrderPolicyEnum.Monthly, dtbWorkingDays, dtbHolidays);
						}
						else if (drowPolicys[ITM_OrderPolicyTable.CODE_FLD].ToString() == OrderPolicyEnum.Quarterly.ToString().ToUpper())
						{
							dstRealCPO = GroupByOrderPolicys(drowItem, dstRealCPO, dstCPO, OrderPolicyEnum.Quarterly, dtbWorkingDays, dtbHolidays);
						}
						else if (drowPolicys[ITM_OrderPolicyTable.CODE_FLD].ToString() == OrderPolicyEnum.Yearly.ToString().ToUpper())
						{
							dstRealCPO = GroupByOrderPolicys(drowItem, dstRealCPO, dstCPO, OrderPolicyEnum.Yearly, dtbWorkingDays, dtbHolidays);
						}
						else
						{
							DataRow[] drowAllItemCPO = dstCPO.Tables[0].Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowItem[ITM_ProductTable.PRODUCTID_FLD], MTR_CPOTable.DUEDATE_FLD + " ASC");
							int intPolocyDays = 0;
							if (drowPolicys[ITM_OrderPolicyTable.ORDERPOLICYDAYS_FLD].ToString() != string.Empty)
								intPolocyDays = (int) decimal.Floor(decimal.Parse(drowPolicys[ITM_OrderPolicyTable.ORDERPOLICYDAYS_FLD].ToString()));
							if (intPolocyDays >= 1)
							{
								int intN = 0, intResult = 0;
								DateTime dtmMaxDate = DateTime.Parse(drowAllItemCPO[drowAllItemCPO.Length-1][MTR_CPOTable.DUEDATE_FLD].ToString());
								intN = Math.DivRem(dtmMaxDate.Subtract(voCOMaster.AsOfDate).Days, intPolocyDays,out intResult);
								if (intN * intPolocyDays <  dtmMaxDate.Subtract(voCOMaster.AsOfDate).Days) intN++;
								for (int i = 0; i < intN; i++)
								{
									decimal decQuantity = 0;
									DateTime dtmDueDate = new DateTime();
									int intFirst = 0;
									for (int j =0; j < drowAllItemCPO.Length; j++)
									{
										if (DateTime.Parse(drowAllItemCPO[j][MTR_CPOTable.DUEDATE_FLD].ToString()) >= voCOMaster.AsOfDate.AddDays(intPolocyDays*i)
											&& DateTime.Parse(drowAllItemCPO[j][MTR_CPOTable.DUEDATE_FLD].ToString()) <= voCOMaster.AsOfDate.AddDays(intPolocyDays* (i+1)))
										{
											decQuantity += decimal.Parse(drowAllItemCPO[j][MTR_CPOTable.QUANTITY_FLD].ToString());
											if (intFirst == 0)
											{
												dtmDueDate = DateTime.Parse(drowAllItemCPO[j][MTR_CPOTable.DUEDATE_FLD].ToString());                                                                                                                   
											}
											intFirst++;
										}
										if ((DateTime) drowAllItemCPO[j][MTR_CPOTable.DUEDATE_FLD] > voCOMaster.AsOfDate.AddDays(intPolocyDays* (i+1))) 
										{
											intFirst = 0;
											break;
										}
									}
									if (decQuantity > 0)	
									{
										DataRow drowNewCPO = dstRealCPO.Tables[0].NewRow();
										drowNewCPO[MTR_CPOTable.PRODUCTID_FLD] = drowItem[ITM_ProductTable.PRODUCTID_FLD];
										drowNewCPO[MTR_CPOTable.STOCKUMID_FLD] = drowItem[ITM_ProductTable.STOCKUMID_FLD];
										drowNewCPO[MTR_CPOTable.CCNID_FLD] = drowAllItemCPO[0][MTR_CPOTable.CCNID_FLD];
										drowNewCPO[MTR_CPOTable.MASTERLOCATIONID_FLD] = drowAllItemCPO[0][MTR_CPOTable.MASTERLOCATIONID_FLD];
										drowNewCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, decQuantity);
										double dblSaleATP = 0, dblBOMLeadtimeOffset = 0;
										try
										{
											dblSaleATP = Convert.ToDouble(drowItem[ITM_ProductTable.LTSALESATP_FLD]);
										}
										catch{}
										drowNewCPO[MTR_CPOTable.DUEDATE_FLD] = dtmDueDate.AddDays( - dblSaleATP - dblBOMLeadtimeOffset);
										drowNewCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, dtbWorkingDays, dtbHolidays, dtmDueDate, decQuantity);
										drowNewCPO[MTR_CPOTable.ISMPS_FLD] = false;
										dstRealCPO.Tables[0].Rows.Add(drowNewCPO);
									}
								}
							}
							else
							{
								foreach (DataRow drowCPO in drowAllItemCPO)
								{
									drowCPO[MTR_CPOTable.QUANTITY_FLD] = GetQuantityForCPO(drowItem, (decimal)drowCPO[MTR_CPOTable.QUANTITY_FLD]);
									drowCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, dtbWorkingDays, dtbHolidays, (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD], (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
									drowCPO[MTR_CPOTable.ISMPS_FLD] = false;
									dstRealCPO.Tables[0].ImportRow(drowCPO);
								}
							}
						}
					}
					
					else
					{
						DataRow[] arldrowCPO  = dstCPO.Tables[0].Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowItem[ITM_ProductTable.PRODUCTID_FLD], MTR_CPOTable.DUEDATE_FLD + " ASC");
						foreach (DataRow drowCPO in arldrowCPO)
						{
							drowCPO[MTR_CPOTable.QUANTITY_FLD] = GetQuantityForCPO(drowItem, (decimal)drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, dtbWorkingDays, dtbHolidays, (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD], (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.ISMPS_FLD] = false;
							dstRealCPO.Tables[0].ImportRow(drowCPO);
						}
					} 
				}
				//Update dataset
				for (int i =0; i <dstRealCPO.Tables[0].Rows.Count; i++)
				{
					dstRealCPO.Tables[0].Rows[i][MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD] = pintMRPCycleOptionMasterID;
				}
				UpdateCPODataset(dstRealCPO, pintMRPCycleOptionMasterID, dtbBeginNIGURI, voCOMaster.AsOfDate, dtmToDate, pintCCN,
					pstrVendorID, pstrCategoryID, pstrModel, pstrProductID);
			}
		}
	
		//[AutoComplete(true)]
		public void UpdateCPODataset(DataSet pdstData, int pintMRPCycleOptionMasterID, DataTable pdtbBeginNIGURI,
			DateTime pdtmFromDate, DateTime pdtmToDate, int pintCCNID,
			string pstrVendorID, string pstrCategoryID, string pstrModel, string pstrProductID)
		{
			MTR_CPODS dsCPO = new MTR_CPODS();
			dsCPO.UpdateDataSet(pdstData);

			MTR_MRPCycleOptionMasterDS dsMRPCycle = new MTR_MRPCycleOptionMasterDS();
			dsMRPCycle.UpdateGenDate(pintMRPCycleOptionMasterID);

			MRPRegenerationProcessDS dsMRP = new MRPRegenerationProcessDS();
			dsMRP.UpdateBeginMRP(pdtbBeginNIGURI.DataSet);

			// close local PO in cycle
			dsMRP.ClosePOInRange(pdtmFromDate, pdtmToDate, pintCCNID, pstrVendorID, pstrCategoryID, pstrModel, pstrProductID);
		}
		
		private void UpdateBegin(int pintMRPCycleOptionMasterID, DataTable pdtbBeginNIGURI,
			DateTime pdtmFromDate, DateTime pdtmToDate, int pintCCNID,
			string pstrVendorID, string pstrCategoryID, string pstrModel, string pstrProductID)
		{
			MTR_MRPCycleOptionMasterDS dsMRPCycle = new MTR_MRPCycleOptionMasterDS();
			dsMRPCycle.UpdateGenDate(pintMRPCycleOptionMasterID);

			MRPRegenerationProcessDS dsMRP = new MRPRegenerationProcessDS();
			dsMRP.UpdateBeginMRP(pdtbBeginNIGURI.DataSet);

			// close local PO in cycle
			dsMRP.ClosePOInRange(pdtmFromDate, pdtmToDate, pintCCNID, pstrVendorID, pstrCategoryID, pstrModel, pstrProductID);
		}
		/// <summary>
		/// Import all rows form source table to destination table
		/// </summary>
		/// <param name="pdtbDes"></param>
		/// <param name="pdtbSource"></param>
		/// <returns></returns>
		private DataTable ImportRows(DataTable pdtbDes, DataTable pdtbSource, int pintType)
		{
			try
			{
				foreach (DataRow drowSource in pdtbSource.Rows)
				{
					DataRow drowDes = pdtbDes.NewRow();
					if (pintType == 0)
						drowDes[MTR_CPOTable.DUEDATE_FLD] = drowSource[MTR_CPOTable.DUEDATE_FLD];
					else 
					{
//						drowDes[MTR_CPOTable.DUEDATE_FLD] = ((DateTime) drowSource[MTR_CPOTable.STARTDATE_FLD]).AddSeconds((int)drowSource[ITM_BOMTable.LEADTIMEOFFSET_FLD]);
						drowDes[MTR_CPOTable.DUEDATE_FLD] = drowSource[MTR_CPOTable.STARTDATE_FLD];
					}
					drowDes[REQUEST_WO_QTITY_FLD] = drowSource[REQUEST_WO_QTITY_FLD];
					pdtbDes.Rows.Add(drowDes);
				}
				return pdtbDes;
			}
			catch (PCSDBException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				throw new Exception(ex.Message, ex);
			}
		}


		/// <summary>
		/// Import all rows form source table to destination table
		/// </summary>
		/// <param name="pdtbDes"></param>
		/// <param name="pdtbSource"></param>
		/// <returns></returns>
		private DataTable ImportAllRows(DataTable pdtbDes, DataTable pdtbSource, int pintType)
		{
			foreach (DataRow drowSource in pdtbSource.Rows)
			{
				DataRow drowDes = pdtbDes.NewRow();
				if (pintType == 0)
					drowDes[MTR_CPOTable.DUEDATE_FLD] = drowSource[MTR_CPOTable.DUEDATE_FLD];
				else 
					drowDes[MTR_CPOTable.DUEDATE_FLD] = drowSource[MTR_CPOTable.STARTDATE_FLD];
				drowDes[ITM_ProductTable.PRODUCTID_FLD] = drowSource[ITM_ProductTable.PRODUCTID_FLD];
				drowDes[REQUEST_WO_QTITY_FLD] = drowSource[REQUEST_WO_QTITY_FLD];
				pdtbDes.Rows.Add(drowDes);
			}
			return pdtbDes;
		}


		/// <summary>
		/// Sort datatable by DateTime column
		/// </summary>
		/// <param name="pdtbSource"></param>
		/// <param name="pstrColumnName"></param>
		/// <returns></returns>
		private DataTable SortTable(DataTable pdtbSource, string pstrColumnName)
		{
			try
			{
				for (int i =0; i < pdtbSource.Rows.Count; i++)
					for (int j = i+1; j < pdtbSource.Rows.Count; j++)
					{
						if ((DateTime)pdtbSource.Rows[i][pstrColumnName] > (DateTime)pdtbSource.Rows[j][pstrColumnName])
						{
							decimal intTempQtity = (decimal) pdtbSource.Rows[i][REQUEST_WO_QTITY_FLD];
							DateTime dtmTempDate = (DateTime) pdtbSource.Rows[i][pstrColumnName];
							pdtbSource.Rows[i][REQUEST_WO_QTITY_FLD] = pdtbSource.Rows[j][REQUEST_WO_QTITY_FLD];
							pdtbSource.Rows[i][pstrColumnName] = pdtbSource.Rows[j][pstrColumnName];
							pdtbSource.Rows[j][REQUEST_WO_QTITY_FLD] = intTempQtity;
							pdtbSource.Rows[j][pstrColumnName] = dtmTempDate;
						}
					}
				return pdtbSource;
			}
			catch (PCSDBException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				throw new Exception(ex.Message, ex);
			}
		}


		/// <summary>
		/// Sort datatable by DateTime column
		/// </summary>
		/// <param name="pdrowListItems"></param>
		/// <param name="pstrColumnName"></param>
		/// <returns></returns>
		private DataRow[] SortListItems(DataRow[] pdrowListItems, string pstrColumnName)
		{
			try
			{
				for (int i =0; i < pdrowListItems.Length; i++)
					for (int j = i+1; j < pdrowListItems.Length; j++)
					{
						if ((DateTime)pdrowListItems[i][pstrColumnName] > (DateTime)pdrowListItems[j][pstrColumnName])
						{
							decimal intTempQtity = decimal.Parse(pdrowListItems[i][REQUEST_WO_QTITY_FLD].ToString());
							DateTime dtmTempDate = DateTime.Parse(pdrowListItems[i][pstrColumnName].ToString());
							pdrowListItems[i][REQUEST_WO_QTITY_FLD] = pdrowListItems[j][REQUEST_WO_QTITY_FLD];
							pdrowListItems[i][pstrColumnName] = pdrowListItems[j][pstrColumnName];
							pdrowListItems[j][REQUEST_WO_QTITY_FLD] = intTempQtity;
							pdrowListItems[j][pstrColumnName] = dtmTempDate;
						}
					}
				return pdrowListItems;
			}
			catch (PCSDBException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				throw new Exception(ex.Message, ex);
			}
		}


		/// <summary>
		/// Return the DataSet (list of record) by inputing the FieldList and Condition
		/// </summary>
		public void UpdateDataSet(DataSet dstData)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Update into Database
		/// </summary>
		public void Update(object pObjectDetail)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Check if user is setting calendar yet
		/// </summary>
		/// <param name="pobjCycleOption"></param>
		/// <returns>true if setting full calendar else return false</returns>
		/// <author>DungLA</author>
		//[AutoComplete(true)]
		private bool CheckCalendarConfig(object pobjCycleOption)
		{
//			try
//			{
				MST_WorkingDayMasterDS dsWorkingDay = new MST_WorkingDayMasterDS();
				DataSet dstCalendar = dsWorkingDay.GetCalendar();
				MTR_MRPCycleOptionMasterVO voMRPCycle = (MTR_MRPCycleOptionMasterVO)pobjCycleOption;
				DateTime dtmEndCycle = voMRPCycle.AsOfDate.AddDays(voMRPCycle.PlanHorizon);
				for(int i = voMRPCycle.AsOfDate.Year; i <= dtmEndCycle.Year; i++)
				{
					DataRow[] drowsFilter = dstCalendar.Tables[0].Select(MST_WorkingDayMasterTable.YEAR_FLD + " = " + i);
					if(drowsFilter.Length == 0) 
					{
						return false;
					}
				}
				return true;
//			}
//			catch (PCSDBException ex)
//			{
//				throw ex;
//			}
//			catch (Exception ex)
//			{
//				throw ex;
//			}
		}
		

		/// <summary>
		/// Build sqlstatement which contains all items
		/// </summary>
		/// <param name="pdtbItems"></param>
		/// <returns></returns>
		private StringBuilder BuildSQLIN(DataTable pdtbItems)
		{
			StringBuilder strSQL = new StringBuilder();
			strSQL.Append("(0");
			foreach (DataRow drowData in pdtbItems.Rows)
				strSQL.Append(Constants.COMMA).Append(drowData[ITM_ProductTable.PRODUCTID_FLD].ToString());
			strSQL.Append(")");

			return strSQL;
		}


		/// <summary>
		/// Get working date after adding pintNumberOfDay
		/// </summary>
		/// <param name="pdtmDate"></param>
		/// <param name="pdecNumberOfDay"></param>
		/// <param name="penuSchedule">
		/// 1: Forward
		/// 2: Backword
		/// </param>
		/// <returns></returns>
		private DateTime ConvertWorkingDayOffLine(DataTable pdtbAllWorksDay, DataTable pdtbAllHolidays, DateTime pdtmDate , decimal pdecNumberOfDay, ScheduleMethodEnum penuSchedule)
		{
//			try
//			{				
				DateTime dtmConvert = pdtmDate;
				ArrayList arrDayOfWeek = new ArrayList(); 

				int intNumberOfDay = (int)decimal.Floor(pdecNumberOfDay);
				double dblRemainder = (double)(pdecNumberOfDay - (decimal)intNumberOfDay);

				if(pdtbAllWorksDay != null)
				{
					DataRow[] drowWorkingDay = pdtbAllWorksDay.Select(MST_WorkingDayMasterTable.YEAR_FLD + "='" + pdtmDate.Year + "'");
					if(drowWorkingDay.Length != 0)
					{
						DataRow drow = drowWorkingDay[0];

						if(!bool.Parse(drow[MST_WorkingDayMasterTable.MON_FLD].ToString()))
						{
							arrDayOfWeek.Add(DayOfWeek.Monday);
						}

						if(!bool.Parse(drow[MST_WorkingDayMasterTable.TUE_FLD].ToString()))
						{
							arrDayOfWeek.Add(DayOfWeek.Tuesday);
						}

						if(!bool.Parse(drow[MST_WorkingDayMasterTable.WED_FLD].ToString()))
						{
							arrDayOfWeek.Add(DayOfWeek.Wednesday);
						}

						if(!bool.Parse(drow[MST_WorkingDayMasterTable.THU_FLD].ToString()))
						{
							arrDayOfWeek.Add(DayOfWeek.Thursday);
						}

						if(!bool.Parse(drow[MST_WorkingDayMasterTable.FRI_FLD].ToString()))
						{
							arrDayOfWeek.Add(DayOfWeek.Friday);
						}

						if(!bool.Parse(drow[MST_WorkingDayMasterTable.SAT_FLD].ToString()))
						{
							arrDayOfWeek.Add(DayOfWeek.Saturday);
						}

						if(!bool.Parse(drow[MST_WorkingDayMasterTable.SUN_FLD].ToString()))
						{
							arrDayOfWeek.Add(DayOfWeek.Sunday);
						}
					}
				}
				
				ArrayList arrHolidays = new ArrayList();
				if(pdtbAllHolidays != null)
				{
					DataRow[] drowHoliday = pdtbAllHolidays.Select(MST_WorkingDayMasterTable.YEAR_FLD + "='" + pdtmDate.Year + "'");
					if(drowHoliday.Length != 0)
					{	
						//have data--> create new array list to add items
						for(int i =0; i< drowHoliday.Length; i++)
						{
							DateTime dtmTemp = DateTime.Parse(pdtbAllHolidays.Rows[i][MST_WorkingDayDetailTable.OFFDAY_FLD].ToString());
							//truncate hour, minute, second
							dtmTemp = new DateTime(dtmTemp.Year, dtmTemp.Month, dtmTemp.Day);							
							arrHolidays.Add(dtmTemp);
						}
					}
				}
				
				switch(penuSchedule)
				{
						#region Forward

					case ScheduleMethodEnum.Forward:
						for(int i =0; i < intNumberOfDay; i++)
						{						
							//Add day
							dtmConvert = dtmConvert.AddDays(1);
							
							//goto next day if the day is holidayday
							while(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
							{
								dtmConvert = dtmConvert.AddDays(1);
							}
							
							//goto next day if the day is off day
							while(arrDayOfWeek.Contains(dtmConvert.DayOfWeek))
							{
								dtmConvert = dtmConvert.AddDays(1);
								if(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
								{
									dtmConvert = dtmConvert.AddDays(1);
								}
							}

							//goto next day if the day is holidayday
							while(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
							{
								dtmConvert = dtmConvert.AddDays(1);
							}
						}
						//Add remainder
						dtmConvert = dtmConvert.AddDays(dblRemainder);

						//goto next day if the day is holidayday
						while(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
						{
							dtmConvert = dtmConvert.AddDays(1);
						}
						
						//goto next day if the day is off day
						while(arrDayOfWeek.Contains(dtmConvert.DayOfWeek))
						{
							dtmConvert = dtmConvert.AddDays(1);
							if(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
							{
								dtmConvert = dtmConvert.AddDays(1);
							}
						}
						
						//goto next day if the day is holidayday
						while(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
						{
							dtmConvert = dtmConvert.AddDays(1);
						}
						break;

						#endregion

	

					case ScheduleMethodEnum.Backward:
						dtmConvert = dtmConvert.AddDays(-intNumberOfDay);
						bool blnIsOK = false;
						while (!blnIsOK)
						{
							DateTime dtmOld = dtmConvert;
							if(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
							{
								dtmConvert = dtmConvert.AddDays(-1);
							}
							if(arrDayOfWeek.Contains( dtmConvert.DayOfWeek))
							{
								dtmConvert = dtmConvert.AddDays(-1);
							}
							if(dtmOld == dtmConvert) blnIsOK = true;
						}

						
						#region old code

//						for(int i =0; i < intNumberOfDay; i++)
//						{							
//							//Add day
//							dtmConvert = dtmConvert.AddDays(-1);
//							
//							//goto next day if the day is holidayday
//							while(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
//							{
//								dtmConvert = dtmConvert.AddDays(-1);
//							}
//							
//							//goto next day if the day is off day
//							while(arrDayOfWeek.Contains( dtmConvert.DayOfWeek))
//							{
//								dtmConvert = dtmConvert.AddDays(-1);
//								if(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
//								{
//									dtmConvert = dtmConvert.AddDays(-1);
//								}
//							}
//
//							//goto next day if the day is holidayday
//							while(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
//							{
//								dtmConvert = dtmConvert.AddDays(-1);
//							}
//						}
//						
//						//Add remainder
//						dtmConvert = dtmConvert.AddDays(-dblRemainder);
//
//						//goto next day if the day is holidayday
//						while(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
//						{
//							dtmConvert = dtmConvert.AddDays(-1);
//						}
//						
//						//goto next day if the day is off day
//						while(arrDayOfWeek.Contains(dtmConvert.DayOfWeek))
//						{
//							dtmConvert = dtmConvert.AddDays(-1);
//							if(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
//							{
//								dtmConvert = dtmConvert.AddDays(-1);
//							}
//						}
//						
//						//goto next day if the day is holidayday
//						while(arrHolidays.Contains(new DateTime(dtmConvert.Year, dtmConvert.Month, dtmConvert.Day)))
//						{
//							dtmConvert = dtmConvert.AddDays(-1);
//						}

						#endregion

						break;
				}

				return dtmConvert;
//			}
//			catch (PCSException ex)
//			{
//				throw ex.CauseException;
//			}
//			catch (Exception ex)
//			{
//				throw new Exception(ex.Message, ex);
//			}
		}


		private DataSet GroupByOrderPolicys(DataRow drowItem, DataSet pdstRealCPO, DataSet pdstInputCPO, OrderPolicyEnum penumOrderPolicy, DataTable pdtbWorkingDays, DataTable pdtbHolidays)
		{
			DateTime dtmNextStep = new DateTime();
			DataRow[] arldrowCPO;
			switch (penumOrderPolicy)
			{
				case OrderPolicyEnum.Daily:
					#region Group by Day
					arldrowCPO = pdstInputCPO.Tables[0].Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowItem[ITM_ProductTable.PRODUCTID_FLD], MTR_CPOTable.DUEDATE_FLD + " ASC");
					if (arldrowCPO.Length > 0)
					{
						DateTime dtmDueDate = (DateTime) arldrowCPO[arldrowCPO.Length - 1][MTR_CPOTable.DUEDATE_FLD];
						DateTime dtmCPODueDate = new DateTime();
						dtmNextStep = new DateTime(((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]).Year, ((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]).Month, ((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]).Day, 0, 0, 0);
						while (dtmNextStep <= dtmDueDate)
						{
							decimal decQuantity = 0;
							int intFirst = 0;
							foreach (DataRow drowCPO in arldrowCPO)
							{
								if (dtmNextStep <= (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] &&
									(DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] <= new DateTime(dtmNextStep.Year, dtmNextStep.Month, dtmNextStep.Day, 23, 59, 59, 99))
								{
									decQuantity += (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD];
									if (intFirst == 0)
									{
										dtmCPODueDate = (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD];
									}
									intFirst++;
								}
								if ((DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] > dtmDueDate) 
								{
									intFirst = 0;
									break;
								}
							}
							if (decQuantity > 0)
							{
								DataRow drowNewCPO = pdstRealCPO.Tables[0].NewRow();
								drowNewCPO[MTR_CPOTable.PRODUCTID_FLD] = drowItem[ITM_ProductTable.PRODUCTID_FLD];
								drowNewCPO[MTR_CPOTable.STOCKUMID_FLD] = drowItem[ITM_ProductTable.STOCKUMID_FLD];
								drowNewCPO[MTR_CPOTable.CCNID_FLD] = arldrowCPO[0][MTR_CPOTable.CCNID_FLD];
								drowNewCPO[MTR_CPOTable.MASTERLOCATIONID_FLD] = arldrowCPO[0][MTR_CPOTable.MASTERLOCATIONID_FLD];
								drowNewCPO[MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD] = arldrowCPO[0][MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD];
								drowNewCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, decQuantity);
								drowNewCPO[MTR_CPOTable.DUEDATE_FLD] = dtmCPODueDate;
								drowNewCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, dtmCPODueDate, decQuantity);
								drowNewCPO[MTR_CPOTable.ISMPS_FLD] = false;
								pdstRealCPO.Tables[0].Rows.Add(drowNewCPO);
							}
							dtmNextStep = dtmNextStep.AddDays(1);
						}
					}
					else
					{
						foreach (DataRow drowCPO in arldrowCPO)
						{
							drowCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD], (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.ISMPS_FLD] = false;
							pdstRealCPO.Tables[0].ImportRow(drowCPO);
						}
					}
					#endregion
					break;
				case OrderPolicyEnum.Weekly:
					#region Group by Week
					arldrowCPO = pdstInputCPO.Tables[0].Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowItem[ITM_ProductTable.PRODUCTID_FLD], MTR_CPOTable.DUEDATE_FLD + " ASC");
					if (arldrowCPO.Length > 0)
					{
						DateTime dtmDueDate = GetDueDateInOneWeek((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]);
						DateTime dtmCPODueDate = new DateTime();
						dtmNextStep = GetStartDateInOneWeek((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]);
						while (dtmNextStep <= (DateTime) arldrowCPO[arldrowCPO.Length -1][MTR_CPOTable.DUEDATE_FLD])
						{
							decimal decQuantity = 0;
							int intFirst = 0;
							foreach (DataRow drowCPO in arldrowCPO)
							{
								if (dtmNextStep <=(DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] &&
									(DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] <= dtmDueDate)
								{
									decQuantity += (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD];
									if (intFirst == 0)
									{
										dtmCPODueDate = (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD];
									}
									intFirst++;
								}
								if ((DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] > dtmDueDate) 
								{
									intFirst = 0;
									break;
								}
							}
							if (decQuantity > 0)
							{
								DataRow drowNewCPO = pdstRealCPO.Tables[0].NewRow();
								drowNewCPO[MTR_CPOTable.PRODUCTID_FLD] = drowItem[ITM_ProductTable.PRODUCTID_FLD];
								drowNewCPO[MTR_CPOTable.STOCKUMID_FLD] = drowItem[ITM_ProductTable.STOCKUMID_FLD];
								drowNewCPO[MTR_CPOTable.CCNID_FLD] = arldrowCPO[0][MTR_CPOTable.CCNID_FLD];
								drowNewCPO[MTR_CPOTable.MASTERLOCATIONID_FLD] = arldrowCPO[0][MTR_CPOTable.MASTERLOCATIONID_FLD];
								drowNewCPO[MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD] = arldrowCPO[0][MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD];
								drowNewCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, decQuantity);
								drowNewCPO[MTR_CPOTable.DUEDATE_FLD] = dtmCPODueDate;
								drowNewCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, dtmCPODueDate, (decimal)drowNewCPO[MTR_CPOTable.QUANTITY_FLD]);
								drowNewCPO[MTR_CPOTable.ISMPS_FLD] = false;
								pdstRealCPO.Tables[0].Rows.Add(drowNewCPO);
							}
							dtmNextStep = dtmDueDate.AddDays(1);
							dtmDueDate = GetDueDateInOneWeek(dtmNextStep);
							dtmNextStep = GetStartDateInOneWeek(dtmNextStep);
						}
					}
					else
					{
						foreach (DataRow drowCPO in arldrowCPO)
						{
							drowCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD], (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.ISMPS_FLD] = false;
							pdstRealCPO.Tables[0].ImportRow(drowCPO);
						}
					}
					#endregion
					break;
				case OrderPolicyEnum.Monthly:
					#region Group by Month
					arldrowCPO = pdstInputCPO.Tables[0].Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowItem[ITM_ProductTable.PRODUCTID_FLD], MTR_CPOTable.DUEDATE_FLD + " ASC");
					if (arldrowCPO.Length > 0)
					{
						DateTime dtmDueDate = GetDueDateInOneMonth((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]);
						DateTime dtmCPODueDate = new DateTime();
						dtmNextStep = GetStartDateInOneMonth((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]);
						while (dtmNextStep <= (DateTime) arldrowCPO[arldrowCPO.Length -1][MTR_CPOTable.DUEDATE_FLD])
						{
							decimal decQuantity = 0;
							int intFirst = 0;
							foreach (DataRow drowCPO in arldrowCPO)
							{
								if (dtmNextStep <= (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] &&
									(DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] <= dtmDueDate)
								{
									decQuantity += (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD];
									if (intFirst == 0)
									{
										dtmCPODueDate = (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD];
									}
									intFirst++;
								}
								if ((DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] > dtmDueDate) 
								{
									intFirst = 0;
									break;
								}
							}
							if (decQuantity > 0)
							{
								DataRow drowNewCPO = pdstRealCPO.Tables[0].NewRow();
								drowNewCPO[MTR_CPOTable.PRODUCTID_FLD] = drowItem[ITM_ProductTable.PRODUCTID_FLD];
								drowNewCPO[MTR_CPOTable.STOCKUMID_FLD] = drowItem[ITM_ProductTable.STOCKUMID_FLD];
								drowNewCPO[MTR_CPOTable.CCNID_FLD] = arldrowCPO[0][MTR_CPOTable.CCNID_FLD];
								drowNewCPO[MTR_CPOTable.MASTERLOCATIONID_FLD] = arldrowCPO[0][MTR_CPOTable.MASTERLOCATIONID_FLD];
								drowNewCPO[MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD] = arldrowCPO[0][MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD];
								drowNewCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, decQuantity);
								drowNewCPO[MTR_CPOTable.DUEDATE_FLD] = dtmCPODueDate;
								drowNewCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, dtmCPODueDate, decQuantity);
								drowNewCPO[MTR_CPOTable.ISMPS_FLD] = false;
								pdstRealCPO.Tables[0].Rows.Add(drowNewCPO);
							}
							dtmNextStep = dtmDueDate.AddDays(1);
							dtmDueDate = GetDueDateInOneMonth(dtmNextStep);
							dtmNextStep = GetStartDateInOneMonth(dtmNextStep);
						}
					}
					else
					{
						foreach (DataRow drowCPO in arldrowCPO)
						{
							drowCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD], (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.ISMPS_FLD] = false;
							pdstRealCPO.Tables[0].ImportRow(drowCPO);
						}
					}
					#endregion
					break;
				case OrderPolicyEnum.Quarterly:
					#region Group by Quarterly
					arldrowCPO = pdstInputCPO.Tables[0].Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowItem[ITM_ProductTable.PRODUCTID_FLD], MTR_CPOTable.DUEDATE_FLD + " ASC");
					if (arldrowCPO.Length > 0)
					{
						DateTime dtmDueDate = GetDueDateInOneQuarter((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]);
						DateTime dtmCPODueDate = new DateTime();
						dtmNextStep = GetStartDateInOneQuarter((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]);
						while (dtmNextStep <= (DateTime) arldrowCPO[arldrowCPO.Length -1][MTR_CPOTable.DUEDATE_FLD])
						{
							decimal decQuantity = 0;
							int intFirst = 0;
							foreach (DataRow drowCPO in arldrowCPO)
							{
								if (dtmNextStep <= (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] &&
									(DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] <= dtmDueDate)
								{
									decQuantity += (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD];
									if (intFirst == 0)
									{
										dtmCPODueDate = (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD];
									}
									intFirst++;
								}
								if ((DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] > dtmDueDate) 
								{
									intFirst = 0;
									break;
								}
							}
							if (decQuantity > 0)
							{
								DataRow drowNewCPO = pdstRealCPO.Tables[0].NewRow();
								drowNewCPO[MTR_CPOTable.PRODUCTID_FLD] = drowItem[ITM_ProductTable.PRODUCTID_FLD];
								drowNewCPO[MTR_CPOTable.STOCKUMID_FLD] = drowItem[ITM_ProductTable.STOCKUMID_FLD];
								drowNewCPO[MTR_CPOTable.CCNID_FLD] = arldrowCPO[0][MTR_CPOTable.CCNID_FLD];
								drowNewCPO[MTR_CPOTable.MASTERLOCATIONID_FLD] = arldrowCPO[0][MTR_CPOTable.MASTERLOCATIONID_FLD];
								drowNewCPO[MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD] = arldrowCPO[0][MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD];
								drowNewCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, decQuantity);
								drowNewCPO[MTR_CPOTable.DUEDATE_FLD] = dtmCPODueDate;
								drowNewCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, dtmCPODueDate, decQuantity);
								drowNewCPO[MTR_CPOTable.ISMPS_FLD] = false;
								pdstRealCPO.Tables[0].Rows.Add(drowNewCPO);
							}
							dtmNextStep = dtmDueDate.AddDays(1);
							dtmDueDate = GetDueDateInOneQuarter(dtmNextStep);
							dtmNextStep = GetStartDateInOneQuarter(dtmNextStep);
						}
					}
					else
					{
						foreach (DataRow drowCPO in arldrowCPO)
						{
							drowCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD], (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.ISMPS_FLD] = false;
							pdstRealCPO.Tables[0].ImportRow(drowCPO);
						}
					}
					#endregion
					break;
				case OrderPolicyEnum.Yearly:
					#region Group by Quarterly
					arldrowCPO = pdstInputCPO.Tables[0].Select(ITM_ProductTable.PRODUCTID_FLD + "=" + drowItem[ITM_ProductTable.PRODUCTID_FLD], MTR_CPOTable.DUEDATE_FLD + " ASC");
					if (arldrowCPO.Length > 0)
					{
						DateTime dtmDueDate = GetDueDateInOneYear((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]);
						DateTime dtmCPODueDate = new DateTime();
						dtmNextStep = GetStartDateInOneYear((DateTime) arldrowCPO[0][MTR_CPOTable.DUEDATE_FLD]);
						while (dtmNextStep <= (DateTime) arldrowCPO[arldrowCPO.Length -1][MTR_CPOTable.DUEDATE_FLD])
						{
							decimal decQuantity = 0;
							int intFirst = 0;
							foreach (DataRow drowCPO in arldrowCPO)
							{
								if (dtmNextStep <= (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] &&
									(DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] <= dtmDueDate)
								{
									decQuantity += (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD];
									if (intFirst == 0)
									{
										dtmCPODueDate = (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD];
									}
									intFirst++;
								}
								if ((DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD] > dtmDueDate) 
								{
									intFirst = 0;
									break;
								}
							}
							if (decQuantity > 0)
							{
								DataRow drowNewCPO = pdstRealCPO.Tables[0].NewRow();
								drowNewCPO[MTR_CPOTable.PRODUCTID_FLD] = drowItem[ITM_ProductTable.PRODUCTID_FLD];
								drowNewCPO[MTR_CPOTable.STOCKUMID_FLD] = drowItem[ITM_ProductTable.STOCKUMID_FLD];
								drowNewCPO[MTR_CPOTable.CCNID_FLD] = arldrowCPO[0][MTR_CPOTable.CCNID_FLD];
								drowNewCPO[MTR_CPOTable.MASTERLOCATIONID_FLD] = arldrowCPO[0][MTR_CPOTable.MASTERLOCATIONID_FLD];
								drowNewCPO[MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD] = arldrowCPO[0][MTR_CPOTable.MRPCYCLEOPTIONMASTERID_FLD];
								drowNewCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, decQuantity);
								drowNewCPO[MTR_CPOTable.DUEDATE_FLD] = dtmCPODueDate;
								drowNewCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, dtmCPODueDate, decQuantity);
								drowNewCPO[MTR_CPOTable.ISMPS_FLD] = false;
								pdstRealCPO.Tables[0].Rows.Add(drowNewCPO);
							}
							dtmNextStep = dtmDueDate.AddDays(1);
							dtmDueDate = GetDueDateInOneYear(dtmNextStep);
							dtmNextStep = GetStartDateInOneYear(dtmNextStep);
						}
					}
					else
					{
						foreach (DataRow drowCPO in arldrowCPO)
						{
							drowCPO[MTR_CPOTable.QUANTITY_FLD]  = GetQuantityForCPO(drowItem, (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.STARTDATE_FLD] = GetStartDateForCPO(drowItem, pdtbWorkingDays, pdtbHolidays, (DateTime) drowCPO[MTR_CPOTable.DUEDATE_FLD], (decimal) drowCPO[MTR_CPOTable.QUANTITY_FLD]);
							drowCPO[MTR_CPOTable.ISMPS_FLD] = false;
							pdstRealCPO.Tables[0].ImportRow(drowCPO);
						}
					}
					#endregion
					break;
			}
			return pdstRealCPO;
		}
		
		/// <summary>
		/// </summary>
		/// <param name="pdtmInDate"></param>
		/// <returns></returns>
		private DateTime GetDueDateInOneWeek(DateTime pdtmInDate)
		{
			DateTime dtmOutDate = new DateTime(pdtmInDate.Year, pdtmInDate.Month, pdtmInDate.Day, 23, 59, 59, 99);
			while (dtmOutDate.DayOfWeek != DayOfWeek.Sunday)
			{
				dtmOutDate = dtmOutDate.AddDays(1);
			}
			return dtmOutDate;
		}

		private DateTime GetStartDateInOneWeek(DateTime pdtmInDate)
		{
			DateTime dtmOutDate = new DateTime(pdtmInDate.Year, pdtmInDate.Month, pdtmInDate.Day, 0, 0, 0, 0);
			while (dtmOutDate.DayOfWeek != DayOfWeek.Monday)
			{
				dtmOutDate = dtmOutDate.AddDays(-1);
			}
			return dtmOutDate;
		}

		private DateTime GetDueDateInOneMonth(DateTime pdtmInDate)
		{
			DateTime dtmOutDate = new DateTime(pdtmInDate.Year, pdtmInDate.Month, 1, 23, 59, 59, 99);

			if (pdtmInDate.Month == 1 || pdtmInDate.Month == 3 || pdtmInDate.Month == 5 || pdtmInDate.Month == 7
			|| pdtmInDate.Month == 8 || pdtmInDate.Month == 10 || pdtmInDate.Month == 12)
			{
				dtmOutDate = dtmOutDate.AddDays(30);
			}
			else if (pdtmInDate.Month == 2)
			{
				while (dtmOutDate.Month == dtmOutDate.AddDays(1).Month)
				{
					dtmOutDate = dtmOutDate.AddDays(1);
				}	
			}
			else dtmOutDate = dtmOutDate.AddDays(29);
			return dtmOutDate;
		}

		private DateTime GetStartDateInOneMonth(DateTime pdtmInDate)
		{
			DateTime dtmOutDate = new DateTime(pdtmInDate.Year, pdtmInDate.Month, 1, 0, 0, 0, 0);
			return dtmOutDate;
		}

		private DateTime GetDueDateInOneQuarter(DateTime pdtmInDate)
		{
			DateTime dtmOutDate = new DateTime();
				
			if (pdtmInDate.Month <= 3)
			{
				dtmOutDate = new DateTime(pdtmInDate.Year, 3, 31, 23, 59, 59, 99);
			}
			else if (pdtmInDate.Month <= 6)
			{
				dtmOutDate = new DateTime(pdtmInDate.Year, 6, 30, 23, 59, 59, 99);
			}
			else if (pdtmInDate.Month <= 9)
			{
				dtmOutDate = new DateTime(pdtmInDate.Year, 9, 30, 23, 59, 59, 99);
			}
			else if (pdtmInDate.Month <= 12)
			{
				dtmOutDate = new DateTime(pdtmInDate.Year, 12, 31, 23, 59, 59, 99);
			}
			return dtmOutDate;
		}

		private DateTime GetStartDateInOneQuarter(DateTime pdtmInDate)
		{
			DateTime dtmOutDate = new DateTime();
				
			if (pdtmInDate.Month <= 3)
			{
				dtmOutDate = new DateTime(pdtmInDate.Year, 1, 1, 0, 0, 0, 0);
			}
			else if (pdtmInDate.Month <= 6)
			{
				dtmOutDate = new DateTime(pdtmInDate.Year, 4, 1, 0, 0, 0, 0);
			}
			else if (pdtmInDate.Month <= 9)
			{
				dtmOutDate = new DateTime(pdtmInDate.Year, 7, 1, 0, 0, 0, 0);
			}
			else if (pdtmInDate.Month <= 12)
			{
				dtmOutDate = new DateTime(pdtmInDate.Year, 10, 1, 0, 0, 0, 0);
			}
			return dtmOutDate;
		}

		private DateTime GetStartDateInOneYear(DateTime pdtmInDate)
		{
			DateTime dtmOutDate = new DateTime(pdtmInDate.Year, 1, 1, 0, 0, 0, 0);
			return dtmOutDate;
		}

		private DateTime GetDueDateInOneYear(DateTime pdtmInDate)
		{
			DateTime dtmOutDate = new DateTime(pdtmInDate.Year, 12, 31, 23, 59, 59, 99);
			return dtmOutDate;
		}

		private DateTime GetStartDateForCPO(DataRow drowItem, DataTable pdtbWorkingDays, DataTable pdtbHolidays,DateTime pdtmCPODueDate, decimal pdecQuantity)
		{
			decimal decLTFixedTime = 0, decLTVari = 0, decLTDock = 0, decSafe = 0, decShip = 0, decRequis = 0;
			if (drowItem[ITM_ProductTable.LTFIXEDTIME_FLD].ToString() != string.Empty)
			{
				decLTFixedTime = decimal.Parse(drowItem[ITM_ProductTable.LTFIXEDTIME_FLD].ToString());
			}
			if (drowItem[ITM_ProductTable.LTVARIABLETIME_FLD].ToString() != string.Empty)
			{
				decLTVari = decimal.Parse(drowItem[ITM_ProductTable.LTVARIABLETIME_FLD].ToString());
			}
			if (drowItem[ITM_ProductTable.LTDOCKTOSTOCK_FLD].ToString() != string.Empty)
			{
				decLTDock = decimal.Parse(drowItem[ITM_ProductTable.LTDOCKTOSTOCK_FLD].ToString());
			}

			if (drowItem[ITM_ProductTable.LTSAFETYSTOCK_FLD].ToString() != string.Empty)
			{
				decSafe = decimal.Parse(drowItem[ITM_ProductTable.LTSAFETYSTOCK_FLD].ToString());
			}
			if (drowItem[ITM_ProductTable.LTSHIPPINGPREPARE_FLD].ToString() != string.Empty)
			{
				decShip = decimal.Parse(drowItem[ITM_ProductTable.LTSHIPPINGPREPARE_FLD].ToString());
			}
			if (drowItem[ITM_ProductTable.LTREQUISITION_FLD].ToString() != string.Empty)
			{
				decRequis = decimal.Parse(drowItem[ITM_ProductTable.LTREQUISITION_FLD].ToString());
			}
			return ConvertWorkingDayOffLine(pdtbWorkingDays, pdtbHolidays, pdtmCPODueDate, Math.Abs(decLTFixedTime/(60*60*24) + pdecQuantity*decLTVari/(60*60*24) + decLTDock/(60*60*24) + decSafe/(60*60*24) +      decShip/(60*60*24) + decRequis/(60*60*24)), ScheduleMethodEnum.Backward);
		}

		private decimal GetQuantityForCPO(DataRow drowItem, decimal pdecQuantity)
		{
			#region remove minorder and multiple order

			//			if (drowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString().Trim() != string.Empty && pdecQuantity < decimal.Parse(drowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString()))
//			{
//				pdecQuantity = decimal.Parse(drowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString());
//			}
//			if (drowItem[ITM_ProductTable.ORDERQUANTITY_FLD].ToString().Trim() != string.Empty && drowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString() != string.Empty 
//				&& decimal.Parse(drowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString()) != 0 
//				&& (pdecQuantity != decimal.Parse(drowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString().Trim()) * decimal.Floor(pdecQuantity/decimal.Parse(drowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString().Trim()))))
//			{
//				pdecQuantity =  (decimal.Floor(pdecQuantity/decimal.Parse(drowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString().Trim())) + 1) *decimal.Parse(drowItem[ITM_ProductTable.ORDERQUANTITYMULTIPLE_FLD].ToString().Trim());
//			}

			#endregion

			return pdecQuantity;
		}

		private decimal GetAllRemainBeforeRun(int pintProductID, DataTable pdtbRequest, DataTable pdtbReplenish)
		{
			decimal decResult = 0;
			object objResult  = pdtbRequest.Compute("Sum(" + REQUEST_WO_QTITY_FLD + ")", ITM_ProductTable.PRODUCTID_FLD + "='" + pintProductID + "'");
			if (objResult != DBNull.Value) 
				decResult = (decimal) objResult;
			objResult = pdtbReplenish.Compute("Sum(" + REPLENISH_PO_QTITY_FLD + ")", ITM_ProductTable.PRODUCTID_FLD + "='" + pintProductID + "'");
			if (objResult != DBNull.Value) 
				decResult = decResult - (decimal) objResult;
		
			 return -decResult;
		}

		/// <summary>
		/// Get prev working day (is not offday)
		/// </summary>
		/// <param name="pdtmDate"></param>
		/// <param name="pdecDay"></param>
		/// <param name="pdstCalendar"></param>
		/// <returns></returns>
		DateTime GetNearestWorkingDay(DateTime pdtmDate, decimal pdecDay, DataSet pdstCalendar)
		{
			int intNumberOfDay = (int)decimal.Floor(pdecDay);
			double dblRemainder = (double)(pdecDay - (decimal)intNumberOfDay);
			pdtmDate = pdtmDate.AddDays(-dblRemainder);
			while(IsOffDay(pdtmDate,pdstCalendar))
			{
				pdtmDate = pdtmDate.AddDays(-1);
			}
			return pdtmDate;
		}

		/// <summary>
		/// Check the day is off day
		/// Return true if isoffday else return false
		/// </summary>
		/// <param name="pdtmDate"></param>
		/// <param name="pdstCalendar"></param>
		/// <returns></returns>
		private bool IsOffDay(DateTime pdtmDate, DataSet pdstCalendar)
		{
			const string METHOD_NAME = ".IsOffDay()";
			DayOfWeek objWeekDay = pdtmDate.DayOfWeek;
			DataRow[] drows = pdstCalendar.Tables[0].Select(MST_WorkingDayMasterTable.YEAR_FLD + " = " + pdtmDate.Year);
			DataRow[] drowDetails = pdstCalendar.Tables[1].Select(MST_WorkingDayDetailTable.OFFDAY_FLD + " = '" + pdtmDate.Date + "'");
			if(drowDetails.Length > 0)
			{
				return true;
			}
			if(drows.Length == 0) // return true;
			{
				throw new PCSBOException(ErrorCode.MESSAGE_DCP_SETTING_WORKING_CALENDAR,METHOD_NAME,null);
			}
			if(objWeekDay == DayOfWeek.Sunday)
			{
				if(bool.Parse(drows[0][MST_WorkingDayMasterTable.SUN_FLD].ToString()) == true) return false;
			}
			else if(objWeekDay == DayOfWeek.Saturday)
			{
				if(bool.Parse(drows[0][MST_WorkingDayMasterTable.SAT_FLD].ToString()) == true) return false;
			}
			else if(objWeekDay == DayOfWeek.Friday)
			{
				if(bool.Parse(drows[0][MST_WorkingDayMasterTable.FRI_FLD].ToString()) == true) return false;
			}
			else if(objWeekDay == DayOfWeek.Thursday)
			{
				if(bool.Parse(drows[0][MST_WorkingDayMasterTable.THU_FLD].ToString()) == true) return false;
			}
			else if(objWeekDay == DayOfWeek.Wednesday)
			{
				if(bool.Parse(drows[0][MST_WorkingDayMasterTable.WED_FLD].ToString()) == true) return false;
			}
			else if(objWeekDay == DayOfWeek.Tuesday)
			{
				if(bool.Parse(drows[0][MST_WorkingDayMasterTable.TUE_FLD].ToString()) == true) return false;
			}
			else if(objWeekDay == DayOfWeek.Monday)
			{
				if(bool.Parse(drows[0][MST_WorkingDayMasterTable.MON_FLD].ToString()) == true) return false;
			}
			return true;
		}
		//[AutoComplete(true)]
		public DataTable GetPONotReceipt(DateTime pdtmFromDate, DateTime pdtmToDate, int pintCCNID)
		{
			MRPRegenerationProcessDS dsProcess = new MRPRegenerationProcessDS();
			return dsProcess.GetPONotReceipt(pdtmFromDate, pdtmToDate, pintCCNID);
		}
		//[AutoComplete(true)]
		public DataTable GetPOReceipt(DateTime pdtmFromDate, DateTime pdtmToDate, int pintCCNID)
		{
			MRPRegenerationProcessDS dsProcess = new MRPRegenerationProcessDS();
			return dsProcess.GetPOReceipt(pdtmFromDate, pdtmToDate, pintCCNID);
		}
		//[AutoComplete(true)]
		public DataTable GetReturnToVendor(DateTime dtmFromDate, DateTime dtmToDate)
		{
			MRPRegenerationProcessDS dsProcess = new MRPRegenerationProcessDS();
			return dsProcess.GetReturnToVendor(dtmFromDate, dtmToDate);
		}
	}
}

 
